Add support for unix-domain sockets on xend.
Remove some dead code.
Signed-off-by: Mike Wray <mike.wray@hp.com>
4267a9b1FfCUjW7m9anLERcx9lwhJg tools/python/xen/web/SrvDir.py
4267a9b1uMXIfzB6-81ZLqMCyTgJmw tools/python/xen/web/__init__.py
4267a9b1i_zVq36tt2iQejVuR6DGFw tools/python/xen/web/connection.py
-4267a9b1Z2SpO9v-zEDApywETZPDwA tools/python/xen/web/defer.py
4267a9b1KzSWZwWKYrGRc9bUhow_7Q tools/python/xen/web/http.py
4267a9b1KWNZhhmZnySe_nLASwO47g tools/python/xen/web/httpserver.py
4267a9b21miObgEJLAgtLTAKRBK8uQ tools/python/xen/web/protocol.py
40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py
40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
-4151594bBq8h-bwTfEt8dbBuojMtcA tools/python/xen/xend/XendAsynchProtocol.py
40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
40eee3a0sPO-WUu34uHUXOC7HliDGw tools/python/xen/xend/XendDmesg.py
40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/python/xen/xend/XendDomain.py
-40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
40ffc44eGsgTEY355E3nN4mPLZHhMQ tools/python/xen/xend/XendLogging.py
40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py
40c9c468S2YnCEKmk4ey8XQIST7INg tools/python/xen/xend/encode.py
4266169ezWIlXSfY50n6HSoVFbosmw tools/python/xen/xend/scheduler.py
-40c9c468DCpMe542varOolW1Xc68ew tools/python/xen/xend/server/SrvBase.py
40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py
40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py
40c9c468woSmBByfeXA4o_jGf2gCgA tools/python/xen/xend/server/SrvDaemon.py
-40c9c468EQZJVkCLds-OhesJVVyZbQ tools/python/xen/xend/server/SrvDir.py
40eee3a0m38EwYXfCSFIjWNwG6jx_A tools/python/xen/xend/server/SrvDmesg.py
40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/python/xen/xend/server/SrvDomain.py
40c9c469WzajDjutou3X7FmL9hMf3g tools/python/xen/xend/server/SrvDomainDir.py
-40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/python/xen/xend/server/SrvEventDir.py
40c9c4694eu5759Dehr4Uhakei0EMg tools/python/xen/xend/server/SrvNode.py
40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
-41ee5e8cFlODpYxhBMZqo9ZgGtcHbg tools/python/xen/xend/server/SrvUsbif.py
40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
4108f181GtRoD1U9TBuJXMfBbGJwdQ tools/python/xen/xend/server/SrvXendLog.py
40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
4266169eI_oX3YBjwaeC0V-THBRnjg tools/python/xen/xend/server/pciif.py
41ee5e8dq9NtihbL4nWKjuSLOhXPUg tools/python/xen/xend/server/usbif.py
40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
-4189125cL90jKSOcBJ3Vx4nWGiXXvA tools/python/xen/xend/util.py
40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
40f552eariuUSB9TWqCPnDLz5zvxMw tools/python/xen/xm/destroy.py
import resource
import http
import httpserver
-import defer
def uri_pathlist(p):
"""Split a path into a list.
def __init__(self, klass):
"""Create a constructor. It is assumed that the class
- should be imported as 'import klass from klass'.
+ should be imported as 'from xen.xend.server.klass import klass'.
klass name of its class
"""
+++ /dev/null
-
-class Deferred:
- pass
import socket
import types
from urllib import quote, unquote
+import os
+import os.path
from xen.xend import sxp
from xen.xend.Args import ArgError
@param val: the value
"""
- if isinstance(val, ThreadRequest):
+ if val is None:
+ return val
+ elif isinstance(val, ThreadRequest):
return val
elif self.useSxp():
self.setHeader("Content-Type", sxp.mime_type)
def getResource(self, req):
return self.root.getRequestResource(req)
+class UnixHttpServer(HttpServer):
-def main():
- root = SrvDir()
- a = root.add("a", SrvDir())
- b = root.add("b", SrvDir())
- server = HttpServer(root=root)
- server.run()
-
-if __name__ == "__main__":
- main()
-
-
+ def __init__(self, path=None, root=None):
+ HttpServer.__init__(self, interface='localhost', root=root)
+ self.path = path
-
-
+ def bind(self):
+ pathdir = os.path.dirname(self.path)
+ if not os.path.exists(pathdir):
+ os.makedirs(pathdir)
+ else:
+ try:
+ os.unlink(self.path)
+ except SystemExit:
+ raise
+ except Exception, ex:
+ pass
+ self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ #self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.socket.bind(self.path)
if self.type:
req.setHeader('Content-Type', self.type)
if self.encoding:
- rew.setHeader('Content-Encoding', self.encoding)
+ req.setHeader('Content-Encoding', self.encoding)
req.setHeader('Content-Length', self.getFileSize())
try:
io = file(self.filename, "r")
io.close()
except:
pass
- return ''
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from twisted.protocols import http
-from twisted.internet.protocol import ClientCreator
-from twisted.internet.defer import Deferred
-from twisted.internet import reactor
-
-from XendProtocol import XendClientProtocol, XendRequest
-
-class AsynchXendClient(http.HTTPClient):
- """A subclass of twisted's HTTPClient to deal with a connection to xend.
- Makes the request when connected, and delegates handling responses etc.
- to its protocol (usually an AsynchXendClientProtocol instance).
- """
- def __init__(self, protocol, request):
- self.protocol = protocol
- self.request = request
-
- def connectionMade(self):
- request = self.request
- url = self.request.url
- self.sendCommand(request.method, url.fullpath())
- self.sendHeader('Host', url.location())
- for (k, v) in request.headers.items():
- self.sendHeader(k, v)
- if request.data:
- self.sendHeader('Content-Length', len(request.data))
- self.endHeaders()
- if request.data:
- self.transport.write(request.data)
-
- def handleStatus(self, version, status, message):
- return self.protocol.handleStatus(version, status, message)
-
- def handleHeader(self, key, val):
- return self.protocol.handleHeader(key, val)
-
- def handleResponse(self, data):
- return self.protocol.handleResponse(data)
-
-class AsynchXendClientProtocol(XendClientProtocol):
- """An asynchronous xend client. Uses twisted to connect to xend
- and make the request. It does not block waiting for the result,
- but sets up a deferred that is called when the result becomes available.
-
- Uses AsynchXendClient to manage the connection.
- """
- def __init__(self):
- self.err = None
- self.headers = {}
-
- def xendRequest(self, url, method, args=None):
- """Make a request to xend. The returned deferred is called when
- the result is available.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- @return: deferred
- """
- request = XendRequest(url, method, args)
- self.deferred = Deferred()
- clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
- clientCreator.connectTCP(url.host, url.port)
- return self.deferred
-
- def callErrback(self, err):
- if not self.deferred.called:
- self.err = err
- self.deferred.errback(err)
- return err
-
- def callCallback(self, val):
- if not self.deferred.called:
- self.deferred.callback(val)
- return val
-
- def handleException(self, err):
- return self.callErrback(err)
-
- def handleHeader(self, key, val):
- self.headers[key.lower()] = val
-
- def getHeader(self, key):
- return self.headers.get(key.lower())
-
- def handleResponse(self, data):
- if self.err: return self.err
- val = XendClientProtocol.handleResponse(self, data)
- if isinstance(val, Exception):
- self.callErrback(val)
- else:
- self.callCallback(val)
- return val
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Client API for the HTTP interface on xend.
Callable as a script - see main().
-Supports synchronous or asynchronous connection to xend.
+Supports inet or unix connection to xend.
This API is the 'control-plane' for xend.
The 'data-plane' is done separately. For example, consoles
import sxp
import PrettyPrint
-from XendProtocol import XendClientProtocol, SynchXendClientProtocol, XendError
+from XendProtocol import HttpXendClientProtocol, \
+ UnixXendClientProtocol, \
+ XendError
DEBUG = 0
return val
raise XendError('cannot convert value')
-# todo: need to sort of what urls/paths are using for objects.
-# e.g. for domains at the moment return '0'.
-# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
-# As an arg, assume abs path is obj uri, otherwise just id.
-
-# Function to convert to full url: Xend.uri(path), e.g.
-# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
-# And should accept urls for ids?
-
class URL:
"""A URL.
"""
@param root: xend root path on the server
"""
if client is None:
- client = SynchXendClientProtocol()
+ client = HttpXendClientProtocol()
self.client = client
self.bind(srv, root)
def vneturl(self, id=''):
return self.url.relative('vnet/' + str(id))
- def eventurl(self, id=''):
- return self.url.relative('event/' + str(id))
-
def xend(self):
return self.xendGet(self.url)
def xend_domain_maxmem_set(self, id, memory):
return self.xendPost(self.domainurl(id),
- { 'op' : 'maxmem_set',
- 'memory' : memory })
+ { 'op' : 'maxmem_set',
+ 'memory' : memory })
+
+ def xend_domain_mem_target_set(self, id, mem_target):
+ val = self.xendPost(self.domainurl(id),
+ {'op' : 'mem_target_set',
+ 'target' : mem_target })
+ return val
def xend_domain_vif_limit(self, id, vif, credit, period):
return self.xendPost(self.domainurl(id),
- { 'op' : 'vif_credit_limit',
+ { 'op' : 'vif_limit_set',
'vif' : vif,
'credit' : credit,
'period' : period })
- def xend_domain_vifs(self, id):
+ def xend_domain_devices(self, id, type):
return self.xendGet(self.domainurl(id),
- { 'op' : 'vifs' })
+ {'op' : 'devices',
+ 'type' : type })
- def xend_domain_vif(self, id, vif):
+ def xend_domain_device(self, id, type, idx):
return self.xendGet(self.domainurl(id),
- { 'op' : 'vif',
- 'vif' : vif })
-
- def xend_domain_vbds(self, id):
- return self.xendGet(self.domainurl(id),
- {'op' : 'vbds'})
-
- def xend_domain_vbd(self, id, vbd):
- return self.xendGet(self.domainurl(id),
- {'op' : 'vbd',
- 'vbd' : vbd })
-
+ {'op' : 'device',
+ 'type' : type,
+ 'idx' : idx })
+
def xend_domain_device_create(self, id, config):
return self.xendPost(self.domainurl(id),
{'op' : 'device_create',
return self.xendPost(self.vneturl(id),
{'op' : 'delete' })
- def xend_event_inject(self, sxpr):
- val = self.xendPost(self.eventurl(),
- {'op' : 'inject',
- 'event' : fileof(sxpr) })
-
- def xend_domain_mem_target_set(self, id, mem_target):
- val = self.xendPost(self.domainurl(id),
- {'op' : 'mem_target_set',
- 'target' : mem_target })
- return val
-
-def getAsynchXendClientProtocol():
- """Load AsynchXendClientProtocol on demand to avoid the cost.
+def getHttpServer(srv=None):
+ """Create and return a xend client.
"""
- global AsynchXendClientProtocol
- try:
- AsynchXendClientProtocol
- except:
- from XendAsynchProtocol import AsynchXendClientProtocol
- return AsynchXendClientProtocol
+ return Xend(srv=srv, client=XendClientProtocol())
-def getAsynchServer():
- """Load AsynchXendClientProtocol and create an asynch xend client.
-
- @return asynch Xend
+def getUnixServer(srv=None):
+ """Create and return a unix-domain xend client.
"""
- getAsynchXendClientProtocol()
- return Xend(AsynchXendClientProtocol())
+ return Xend(client=UnixXendClientProtocol(srv))
-def xendmain(srv, asynch, fn, args):
- if asynch:
- getAsynchXendClientProtocol()
- client = AsynchXendClientProtocol()
+def xendmain(srv, fn, args, unix=False):
+ if unix:
+ xend = getUnixServer(srv)
else:
- client = None
- xend = Xend(srv=srv, client=client)
+ xend = getHttpServer(srv)
xend.rc = 0
try:
v = getattr(xend, fn)(*args)
+ PrettyPrint.prettyprint(v)
+ return 0
except XendError, err:
print 'ERROR:', err
return 1
- if asynch:
- def cbok(val):
- PrettyPrint.prettyprint(val)
- reactor.stop()
- def cberr(err):
- print 'ERROR:', err
- xend.rc = 1
- reactor.stop()
- v.addCallback(cbok)
- v.addErrback(cberr)
- reactor.run()
- return xend.rc
- else:
- PrettyPrint.prettyprint(v)
- return 0
def main(argv):
"""Call an API function:
"""
global DEBUG
from getopt import getopt
- short_options = 'x:ad'
- long_options = ['xend=', 'asynch', 'debug']
+ short_options = 'x:au:d'
+ long_options = ['xend=', 'unix=', 'debug']
(options, args) = getopt(argv[1:], short_options, long_options)
srv = None
- asynch = 0
+ unix = 1
for k, v in options:
if k in ['-x', '--xend']:
srv = v
- elif k in ['-a', '--asynch']:
- asynch = 1
+ elif k in ['-u', '--unix']:
+ unix = int(v)
elif k in ['-d', '--debug']:
DEBUG = 1
if len(args):
args = []
if not fn.startswith('xend'):
fn = 'xend_' + fn
- sys.exit(xendmain(srv, asynch, fn, args))
+ sys.exit(xendmain(srv, fn, args, unix=unix))
if __name__ == "__main__":
main(sys.argv)
else:
- server = Xend()
+ server = getUnixServer()
dominfo = self.domain_lookup(id)
return dominfo.getDeviceByIndex(type, idx)
- def domain_vif_credit_limit(self, id, vif, credit, period):
+ def domain_vif_limit_set(self, id, vif, credit, period):
"""Limit the vif's transmission rate
"""
dominfo = self.domain_lookup(id)
raise XendError("invalid vif")
return dev.setCreditLimit(credit, period)
- def domain_vif_ls(self, id):
- """Get list of virtual network interface (vif) indexes for a domain.
-
- @param id: domain
- @return: vif indexes
- """
- return self.domain_devtype_ls(id, 'vif')
-
- def domain_vif_get(self, id, vif):
- """Get a virtual network interface (vif) from a domain.
-
- @param id: domain
- @param vif: vif index
- @return: vif device object (or None)
- """
- return self.domain_devtype_get(id, 'vif', vif)
-
- def domain_vbd_ls(self, id):
- """Get list of virtual block device (vbd) indexes for a domain.
-
- @param id: domain
- @return: vbd indexes
- """
- return self.domain_devtype_ls(id, 'vbd')
-
- def domain_vbd_get(self, id, vbd):
- """Get a virtual block device (vbd) from a domain.
-
- @param id: domain
- @param vbd: vbd index
- @return: vbd device (or None)
- """
- return self.domain_devtype_get(id, 'vbd', vbd)
-
def domain_shadow_control(self, id, op):
"""Shadow page control.
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for persistent domain configs.
-
-"""
-
-import sxp
-import XendDB
-import XendDomain
-
-__all__ = [ "XendDomainConfig" ]
-
-class XendDomainConfig:
-
- dbpath = 'config'
-
- def __init__(self):
- self.db = XendDB.XendDB(self.dbpath)
-
- def domain_config_ls(self, path):
- return self.db.ls(path)
-
- def domain_config_create(self, path, sxpr):
- self.db.save(path, sxpr)
- pass
-
- def domain_config_delete(self, path):
- self.db.delete(path)
-
- def domain_config_instance(self, path):
- """Create a domain from a config.
- """
- config = self.db.fetch(path)
- xd = XendDomain.instance()
- newdom = xd.domain_create(config)
- return newdom
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = XendDomainConfig()
- return inst
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+import socket
import httplib
import types
"""
raise NotImplementedError()
-class SynchXendClientProtocol(XendClientProtocol):
+class HttpXendClientProtocol(XendClientProtocol):
"""A synchronous xend client. This will make a request, wait for
the reply and return the result.
"""
resp = None
+ request = None
+
+ def makeConnection(self, url):
+ return httplib.HTTPConnection(url.location())
+
+ def makeRequest(self, url, method, args):
+ return XendRequest(url, method, args)
def xendRequest(self, url, method, args=None):
"""Make a request to xend.
@param method: http method: POST or GET
@param args: request arguments (dict)
"""
- self.request = XendRequest(url, method, args)
- conn = httplib.HTTPConnection(url.location())
+ self.request = self.makeRequest(url, method, args)
+ conn = self.makeConnection(url)
if DEBUG: conn.set_debuglevel(1)
conn.request(method, url.fullpath(), self.request.data, self.request.headers)
resp = conn.getresponse()
def getHeader(self, key):
return self.resp.getheader(key)
+class UnixConnection(httplib.HTTPConnection):
+ """Subclass of Python library HTTPConnection that uses a unix-domain socket.
+ """
+
+ def __init__(self, path):
+ httplib.HTTPConnection.__init__(self, 'localhost')
+ self.path = path
+
+ def connect(self):
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ sock.connect(self.path)
+ self.sock = sock
+
+class UnixXendClientProtocol(HttpXendClientProtocol):
+ """A synchronous xend client using a unix-domain socket.
+ """
+
+ XEND_PATH_DEFAULT = '/var/lib/xend/xend-socket'
+
+ def __init__(self, path=None):
+ if path is None:
+ path = self.XEND_PATH_DEFAULT
+ self.path = path
+
+ def makeConnection(self, url):
+ return UnixConnection(self.path)
import EventServer
from XendLogging import XendLogging
+from XendError import XendError
# Initial create of the event server.
eserver = EventServer.instance()
loglevel_default = 'DEBUG'
+ """Default for the flag indicating whether xend should run an http server."""
+ xend_http_server_default = 'no'
+
"""Default interface address xend listens at. """
xend_address_default = ''
"""Default port xend serves events at. """
xend_event_port_default = '8001'
- """Default inteface address xend listens at for consoles."""
+ """Default for the flag indicating whether xend should run a unix-domain server."""
+ xend_unix_server_default = 'yes'
+
+ """Default path the unix-domain server listens at."""
+ xend_unix_path_default = '/var/lib/xend/xend-socket'
+
+ """Default interface address xend listens at for consoles."""
console_address_default = ''
"""Default port xend serves consoles at. """
logfile = self.get_config_value("logfile", self.logfile_default)
loglevel = self.get_config_value("loglevel", self.loglevel_default)
self.logging = XendLogging(logfile, level=loglevel)
+ self.logging.addLogStderr()
def get_logging(self):
"""Get the XendLogging instance.
"""
return sxp.child_value(self.config, name, val=val)
+ def get_config_bool(self, name, val=None):
+ v = self.get_config_value(name, val)
+ if v in ['yes', '1', 'on', 1, True]:
+ return True
+ if v in ['no', '0', 'off', 0, False]:
+ return False
+ raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
+
+ def get_config_int(self, name, val=None):
+ v = self.get_config_value(name, val)
+ try:
+ return int(v)
+ except Exception, ex:
+ raise XendError("invalid xend config %s: expected int: %s" % (name, v))
+
+ def get_xend_http_server(self):
+ """Get the flag indicating whether xend should run an http server.
+ """
+ return self.get_config_bool("xend-http-server", self.xend_http_server_default)
+
def get_xend_port(self):
"""Get the port xend listens at for its HTTP interface.
"""
- return int(self.get_config_value('xend-port', self.xend_port_default))
+ return self.get_config_int('xend-port', self.xend_port_default)
def get_xend_event_port(self):
"""Get the port xend listens at for connection to its event server.
"""
- return int(self.get_config_value('xend-event-port', self.xend_event_port_default))
+ return self.get_config_int('xend-event-port', self.xend_event_port_default)
def get_xend_address(self):
"""Get the address xend listens at for its HTTP and event ports.
"""
return self.get_config_value('xend-address', self.xend_address_default)
+ def get_xend_unix_server(self):
+ """Get the flag indicating whether xend should run a unix-domain server.
+ """
+ return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
+
+ def get_xend_unix_path(self):
+ """Get the path the xend unix-domain server listens at.
+ """
+ return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
+
def get_console_address(self):
"""Get the address xend listens at for its console ports.
This defaults to the empty string which allows all hosts to connect.
def get_console_port_base(self):
"""Get the base port number used to generate console ports for domains.
"""
- return int(self.get_config_value('console-port-base', self.console_port_base_default))
+ return self.get_config_int('console-port-base', self.console_port_base_default)
def get_block_script(self, type):
return self.get_config_value('block-%s' % type, '')
return self.get_config_value('vif-script', 'vif-bridge')
def get_vif_antispoof(self):
- v = self.get_config_value('vif-antispoof', 'yes')
- return v in ['yes', '1', 'on']
+ return self.get_config_bool('vif-antispoof', 'yes')
def instance():
"""Get an instance of XendRoot.
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-from xen.web.SrvBase import *
from xen.xend import sxp
from xen.xend import XendConsole
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvConsole(SrvDir):
"""An individual console.
self.createFactories()
self.listenEvent(xroot)
self.listenChannels()
- serverthread = SrvServer.create(bridge=1)
+ servers = SrvServer.create()
self.daemonize()
print 'running serverthread...'
- serverthread.start()
+ servers.start()
except Exception, ex:
print >>sys.stderr, 'Exception starting xend:', ex
if DEBUG:
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-from xen.web.SrvBase import *
-from xen.web.SrvDir import *
from xen.xend import sxp
from xen.xend import XendDmesg
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvDmesg(SrvDir):
"""Xen Dmesg output.
from xen.xend import PrettyPrint
from xen.xend.Args import FormFn
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvDomain(SrvDir):
"""Service managing a single domain.
return val
def op_pause(self, op, req):
- # Pause doesn't need a thread, but request one for testing.
- return req.threadRequest(self.do_pause, op, req)
-
- def do_pause(self, op, req):
val = self.xd.domain_pause(self.dom.name)
return val
['memory', 'int']])
val = fn(req.args, {'dom': self.dom.id})
return val
+
+ def op_mem_target_set(self, op, req):
+ fn = FormFn(self.xd.domain_mem_target_set,
+ [['dom', 'str'],
+ ['target', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_devices(self, op, req):
+ fn = FormFn(self.xd.domain_devtype_ls,
+ [['dom', 'str'],
+ ['type', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_device(self, op, req):
+ fn = FormFn(self.xd.domain_devtype_get,
+ [['dom', 'str'],
+ ['type', 'str'],
+ ['idx', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ if val:
+ return val.sxpr()
+ else:
+ raise XendError("invalid device")
def op_device_create(self, op, req):
fn = FormFn(self.xd.domain_device_create,
val = fn(req.args, {'dom': self.dom.id})
return val
- def op_vif_credit_limit(self, op, req):
- fn = FormFn(self.xd.domain_vif_credit_limit,
+ def op_vif_limit_set(self, op, req):
+ fn = FormFn(self.xd.domain_vif_limit_set,
[['dom', 'str'],
['vif', 'int'],
['credit', 'int'],
val = fn(req.args, {'dom': self.dom.id})
return val
- def op_vifs(self, op, req):
- devs = self.xd.domain_vif_ls(self.dom.id)
- return [ dev.sxpr() for dev in devs ]
-
- def op_vif(self, op, req):
- fn = FormFn(self.xd.domain_vif_get,
- [['dom', 'str'],
- ['vif', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_vbds(self, op, req):
- devs = self.xd.domain_vbd_ls(self.dom.id)
- return [ dev.sxpr() for dev in devs ]
-
- def op_vbd(self, op, req):
- fn = FormFn(self.xd.domain_vbd_get,
- [['dom', 'str'],
- ['vbd', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_mem_target_set(self, op, req):
- fn = FormFn(self.xd.domain_mem_target_set,
- [['dom', 'str'],
- ['target', 'int']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
def render_POST(self, req):
return self.perform(req)
from xen.xend.XendError import XendError
from xen.xend.XendLogging import log
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
from SrvDomain import SrvDomain
class SrvDomainDir(SrvDir):
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import sxp
-from xen.xend import EventServer
-from SrvDir import SrvDir
-
-class SrvEventDir(SrvDir):
- """Event directory.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.eserver = EventServer.instance()
-
- def op_inject(self, op, req):
- eventstring = req.args.get('event')
- pin = sxp.Parser()
- pin.input(eventstring)
- pin.input_eof()
- sxpr = pin.get_val()
- self.eserver.inject(sxp.name(sxpr), sxpr)
- if req.use_sxp:
- sxp.name(sxpr)
- else:
- return '<code>' + eventstring + '</code>'
-
- def render_POST(self, req):
- return self.perform(req)
-
- def form(self, req):
- action = req.prePathURL()
- req.write('<form method="post" action="%s" enctype="multipart/form-data">'
- % action)
- req.write('<button type="submit" name="op" value="inject">Inject</button>')
- req.write('Event <input type="text" name="event" size="40"><br>')
- req.write('</form>')
- req.write('<form method="post" action="%s" enctype="multipart/form-data">'
- % action)
- req.write('<button type="submit" name="op" value="inject">Inject</button>')
- req.write('Event file<input type="file" name="event"><br>')
- req.write('</form>')
import os
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
from xen.xend import sxp
from xen.xend import XendNode
from xen.xend.Args import FormFn
from xen.xend import XendRoot
xroot = XendRoot.instance()
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvRoot(SrvDir):
"""The root of the xend server.
('node', 'SrvNode' ),
('domain', 'SrvDomainDir' ),
('console', 'SrvConsoleDir' ),
- ('event', 'SrvEventDir' ),
('vnet', 'SrvVnetDir' ),
]
from threading import Thread
-from xen.web.httpserver import HttpServer
+from xen.web.httpserver import HttpServer, UnixHttpServer
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
+from xen.xend import XendRoot; xroot = XendRoot.instance()
from xen.xend import Vifctl
+from xen.web.SrvDir import SrvDir
+
from SrvRoot import SrvRoot
-from SrvDir import SrvDir
-def create(port=None, interface=None, bridge=0):
- if port is None:
- port = xroot.get_xend_port()
- if interface is None:
- interface = xroot.get_xend_address()
- if bridge:
+class XendServers:
+
+ def __init__(self):
+ self.servers = []
+
+ def add(self, server):
+ self.servers.append(server)
+
+ def start(self):
Vifctl.network('start')
+ for server in self.servers:
+ thread = Thread(target=server.run)
+ thread.start()
+
+def create():
root = SrvDir()
root.putChild('xend', SrvRoot())
- server = HttpServer(root=root, interface=interface, port=port)
- thread = Thread(name="XendHttpServer", target=server.run)
- return thread
+ servers = XendServers()
+ if xroot.get_xend_http_server():
+ port = xroot.get_xend_port()
+ interface = xroot.get_xend_address()
+ servers.add(HttpServer(root=root, interface=interface, port=port))
+ if xroot.get_xend_unix_server():
+ path = xroot.get_xend_unix_path()
+ print 'unix path=', path
+ servers.add(UnixHttpServer(path=path, root=root))
+ return servers
+++ /dev/null
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.web import http
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend import XendConsole
-from xen.xend import PrettyPrint
-from xen.xend.Args import FormFn
-
-from SrvDir import SrvDir
-
-class SrvDomain(SrvDir):
- """Service managing a single domain.
- """
-
- def __init__(self, dom):
- SrvDir.__init__(self)
- self.dom = dom
- self.xd = XendDomain.instance()
- self.xconsole = XendConsole.instance()
-
- def op_configure(self, op, req):
- """Configure an existing domain.
- Configure is unusual in that it requires a domain id,
- not a domain name.
- """
- fn = FormFn(self.xd.domain_configure,
- [['dom', 'int'],
- ['config', 'sxpr']])
- deferred = fn(req.args, {'dom': self.dom.dom})
- deferred.addErrback(self._op_configure_err, req)
- return deferred
-
- def _op_configure_err(self, err, req):
- req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
- return str(err)
-
- def op_unpause(self, op, req):
- val = self.xd.domain_unpause(self.dom.name)
- return val
-
- def op_pause(self, op, req):
- val = self.xd.domain_pause(self.dom.name)
- return val
-
- def op_shutdown(self, op, req):
- fn = FormFn(self.xd.domain_shutdown,
- [['dom', 'str'],
- ['reason', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- req.setResponseCode(http.ACCEPTED)
- req.setHeader("Location", "%s/.." % req.prePathURL())
- return val
-
- def op_destroy(self, op, req):
- fn = FormFn(self.xd.domain_destroy,
- [['dom', 'str'],
- ['reason', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- req.setHeader("Location", "%s/.." % req.prePathURL())
- return val
-
- def op_save(self, op, req):
- fn = FormFn(self.xd.domain_save,
- [['dom', 'str'],
- ['file', 'str']])
- deferred = fn(req.args, {'dom': self.dom.id})
- deferred.addCallback(self._op_save_cb, req)
- deferred.addErrback(self._op_save_err, req)
- return deferred
-
- def _op_save_cb(self, val, req):
- return 0
-
- def _op_save_err(self, err, req):
- req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
- return str(err)
-
- def op_migrate(self, op, req):
- fn = FormFn(self.xd.domain_migrate,
- [['dom', 'str'],
- ['destination', 'str'],
- ['live', 'int']])
- deferred = fn(req.args, {'dom': self.dom.id})
- print 'op_migrate>', deferred
- deferred.addCallback(self._op_migrate_cb, req)
- deferred.addErrback(self._op_migrate_err, req)
- return deferred
-
- def _op_migrate_cb(self, info, req):
- print '_op_migrate_cb>', info, req
- #req.setResponseCode(http.ACCEPTED)
- host = info.dst_host
- port = info.dst_port
- dom = info.dst_dom
- url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
- req.setHeader("Location", url)
- print '_op_migrate_cb> url=', url
- return url
-
- def _op_migrate_err(self, err, req):
- print '_op_migrate_err>', err, req
- req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
- return str(err)
-
- def op_pincpu(self, op, req):
- fn = FormFn(self.xd.domain_pincpu,
- [['dom', 'str'],
- ['cpu', 'int']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_cpu_bvt_set(self, op, req):
- fn = FormFn(self.xd.domain_cpu_bvt_set,
- [['dom', 'str'],
- ['mcuadv', 'int'],
- ['warpback', 'int'],
- ['warpvalue', 'int'],
- ['warpl', 'long'],
- ['warpu', 'long']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_cpu_fbvt_set(self, op, req):
- fn = FormFn(self.xd.domain_cpu_fbvt_set,
- [['dom', 'str'],
- ['mcuadv', 'int'],
- ['warp', 'int'],
- ['warpl', 'int'],
- ['warpu', 'int']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_maxmem_set(self, op, req):
- fn = FormFn(self.xd.domain_maxmem_set,
- [['dom', 'str'],
- ['memory', 'int']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_device_create(self, op, req):
- fn = FormFn(self.xd.domain_device_create,
- [['dom', 'str'],
- ['config', 'sxpr']])
- d = fn(req.args, {'dom': self.dom.id})
- return d
-
- def op_device_destroy(self, op, req):
- fn = FormFn(self.xd.domain_device_destroy,
- [['dom', 'str'],
- ['type', 'str'],
- ['idx', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_vifs(self, op, req):
- devs = self.xd.domain_vif_ls(self.dom.id)
- return [ dev.sxpr() for dev in devs ]
-
- def op_vif(self, op, req):
- fn = FormFn(self.xd.domain_vif_get,
- [['dom', 'str'],
- ['vif', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def op_vbds(self, op, req):
- devs = self.xd.domain_vbd_ls(self.dom.id)
- return [ dev.sxpr() for dev in devs ]
-
- def op_vbd(self, op, req):
- fn = FormFn(self.xd.domain_vbd_get,
- [['dom', 'str'],
- ['vbd', 'str']])
- val = fn(req.args, {'dom': self.dom.id})
- return val
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- op = req.args.get('op')
- if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd']:
- return self.perform(req)
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(self.dom.sxpr(), out=req)
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- #self.ls()
- req.write('<p>%s</p>' % self.dom)
- if self.dom.console:
- cinfo = self.dom.console
- cid = str(cinfo.console_port)
- #todo: Local xref: need to know server prefix.
- req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
- % (cid, cid))
- req.write('<p><a href="%s">Connect to console</a></p>'
- % cinfo.uri())
- if self.dom.config:
- req.write("<code><pre>")
- PrettyPrint.prettyprint(self.dom.config, out=req)
- req.write("</pre></code>")
- self.form(req)
- req.write('</body></html>')
- return ''
-
- def form(self, req):
- url = req.prePathURL()
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="unpause">')
- req.write('<input type="submit" name="op" value="pause">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="destroy">')
- req.write('<input type="radio" name="reason" value="halt" checked>Halt')
- req.write('<input type="radio" name="reason" value="reboot">Reboot')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<input type="submit" name="op" value="shutdown">')
- req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
- req.write('<input type="radio" name="reason" value="halt">Halt')
- req.write('<input type="radio" name="reason" value="reboot">Reboot')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<br><input type="submit" name="op" value="save">')
- req.write(' To file: <input type="text" name="file">')
- req.write('</form>')
-
- req.write('<form method="post" action="%s">' % url)
- req.write('<br><input type="submit" name="op" value="migrate">')
- req.write(' To host: <input type="text" name="destination">')
- req.write('<input type="checkbox" name="live" value="1">Live')
- req.write('</form>')
from xen.xend import PrettyPrint
from xen.xend import XendVnet
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvVnet(SrvDir):
from xen.xend import XendRoot
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
class SrvXendLog(SrvDir):
"""Xend log.
for a domain.
"""
- def __init__(self, dctype, vm, recreate=False):
+ def __init__(self, vm, recreate=False):
"""Create a block device controller.
"""
- DevController.__init__(self, dctype, vm, recreate=recreate)
+ DevController.__init__(self, vm, recreate=recreate)
self.backends = {}
self.backendId = 0
self.rcvr = None
def __init__(self):
"""Constructor - do not use. Use the channelFactory function."""
self.notifier = xu.notifier()
+ # Register interest in all virqs.
+ # Unfortunately virqs do not seem to be delivered.
self.bind_virq(VIRQ_MISDIRECT)
self.bind_virq(VIRQ_TIMER)
self.bind_virq(VIRQ_DEBUG)
def main(self):
"""Main routine for the thread.
+ Reads the notifier and dispatches to channels.
"""
while True:
if self.thread == None: return
return inst
class Channel:
+ """Chanel to a domain.
+ Maintains a list of device handlers to dispatch requests to, based
+ on the request type.
+ """
def __init__(self, factory, dom, local_port, remote_port):
self.factory = factory
self.dom = int(dom)
- # Registered devices.
+ # Registered device handlers.
self.devs = []
- # Devices indexed by the message types they handle.
+ # Handlers indexed by the message types they handle.
self.devs_by_type = {}
self.port = self.factory.createPort(self.dom,
local_port=local_port,
remote_port=remote_port)
self.closed = False
+ # Queue of waiters for responses to requests.
self.queue = ResponseQueue(self)
# Make sure the port will deliver all the messages.
self.port.register(TYPE_WILDCARD)
def registerDevice(self, types, dev):
- """Register a device controller.
+ """Register a device message handler.
- @param types: message types the controller handles
+ @param types: message types handled
@type types: array of ints
- @param dev: device controller
+ @param dev: device handler
"""
if self.closed: return
self.devs.append(dev)
self.devs_by_type[ty] = dev
def deregisterDevice(self, dev):
- """Remove the registration for a device controller.
+ """Remove the registration for a device handler.
- @param dev: device controller
+ @param dev: device handler
"""
if dev in self.devs:
self.devs.remove(dev)
del self.devs_by_type[ty]
def getDevice(self, type):
- """Get the device controller handling a message type.
+ """Get the handler for a message type.
@param type: message type
@type type: int
@return: controller or None
- @rtype: device controller
+ @rtype: device handler
"""
return self.devs_by_type.get(type)
def requestReceived(self, msg):
+ """A request has been received on the channel.
+ Disptach it to the device handlers.
+ Called from the channel factory thread.
+ """
if DEBUG:
print 'Channel>requestReceived>', self,
printMsg(msg)
if dev:
responded = dev.requestReceived(msg, ty, subty)
elif DEBUG:
- print "Channel>requestReceived> No device", self,
+ print "Channel>requestReceived> No device handler", self,
printMsg(msg)
else:
pass
self.writeResponse(msg)
def writeRequest(self, msg):
+ """Write a request to the channel.
+ """
if DEBUG:
print 'Channel>writeRequest>', self,
printMsg(msg, all=True)
return 1
def writeResponse(self, msg):
+ """Write a response to the channel.
+ """
if DEBUG:
print 'Channel>writeResponse>', self,
printMsg(msg, all=True)
return 1
def readRequest(self):
+ """Read a request from the channel.
+ Called internally.
+ """
if self.closed:
val = None
else:
return val
def readResponse(self):
+ """Read a response from the channel.
+ Called internally.
+ """
if self.closed:
val = None
else:
return self.queue.call(msg, timeout)
def responseReceived(self, msg):
+ """A response has been received, look for a waiter to
+ give it to.
+ Called internally.
+ """
if DEBUG:
print 'Channel>responseReceived>', self,
printMsg(msg)
def virq(self):
self.factory.virq()
-
class Response:
"""Entry in the response queue.
Used to signal a response to a message.
return r
def response(self, mid, msg):
- """Process a response.
+ """Process a response - signals any waiter that a response
+ has arrived.
"""
try:
self.lock.acquire()
"""Device controller for all the consoles for a domain.
"""
- def __init__(self, dctype, vm, recreate=False):
- DevController.__init__(self, dctype, vm, recreate=recreate)
+ def __init__(self, vm, recreate=False):
+ DevController.__init__(self, vm, recreate=recreate)
self.rcvr = None
def initController(self, recreate=False, reboot=False):
DEBUG = 0
class CtrlMsgRcvr:
- """Dispatcher class for messages on a control channel.
+ """Utility class to dispatch messages on a control channel.
Once I{registerChannel} has been called, our message types are registered
with the channel. The channel will call I{requestReceived}
when a request arrives if it has one of our message types.
if self.channel:
self.channel.deregisterDevice(self)
-class DevControllerType:
- """Abstract class for device controller types.
- """
-
- def __init__(self, type):
- self.type = type
-
- def getType(self):
- """Get the device controller type name.
- """
- return self.type
-
- def createDevController(self, vm, recreate=False):
- """Create a device controller for a domain.
- Must be implemented in subclass.
- """
- raise NotImplementedError()
-
-class SimpleDevControllerType(DevControllerType):
- """Device controller type that simply wraps a controller
- class and uses its constructor to create instances.
- """
-
- def __init__(self, type, devControllerClass):
- DevControllerType.__init__(self, type)
- self.devControllerClass = devControllerClass
-
- def createDevController(self, vm, recreate=False):
- """Create a device controller for a domain.
- """
- ctrl = self.devControllerClass(self, vm, recreate=recreate)
- ctrl.initController(recreate=recreate)
- return ctrl
-
class DevControllerTable:
- """Table of device controller types, indexed by type name.
+ """Table of device controller classes, indexed by type name.
"""
def __init__(self):
- self.controllerTypes = {}
+ self.controllerClasses = {}
- def getDevControllerType(self, type):
- return self.controllerTypes.get(type)
+ def getDevControllerClass(self, type):
+ return self.controllerClasses.get(type)
- def addDevControllerType(self, dctype):
- self.controllerTypes[dctype.getType()] = dctype
- return dctype
+ def addDevControllerClass(self, klass):
+ self.controllerClasses[klass.getType()] = klass
- def delDevControllerType(self, type):
- if type in self.controllerTypes:
- del self.controllerTypes[type]
+ def delDevControllerClass(self, type):
+ if type in self.controllerClasses:
+ del self.controllerClasses[type]
def createDevController(self, type, vm, recreate=False):
- dctype = self.getDevControllerType(type)
- if not dctype:
+ klass = self.getDevControllerClass(type)
+ if not klass:
raise XendError("unknown device type: " + type)
- return dctype.createDevController(vm, recreate=recreate)
+ return klass.createDevController(vm, recreate=recreate)
def getDevControllerTable():
+ """Singleton constructor for the controller table.
+ """
global devControllerTable
try:
devControllerTable
devControllerTable = DevControllerTable()
return devControllerTable
-def addDevControllerType(dctype):
- return getDevControllerTable().addDevControllerType(dctype)
-
def addDevControllerClass(name, klass):
- ty = SimpleDevControllerType(name, klass)
- return addDevControllerType(ty)
+ """Add a device controller class to the controller table.
+ """
+ klass.name = name
+ getDevControllerTable().addDevControllerClass(klass)
def createDevController(name, vm, recreate=False):
return getDevControllerTable().createDevController(name, vm, recreate=recreate)
"""
- def __init__(self, dctype, vm, recreate=False):
- self.dctype = dctype
+ name = None
+
+ def createDevController(klass, vm, recreate=False):
+ """Class method to create a dev controller.
+ """
+ ctrl = klass(vm, recreate=recreate)
+ ctrl.initController(recreate=recreate)
+ return ctrl
+
+ createDevController = classmethod(createDevController)
+
+ def getType(klass):
+ return klass.name
+
+ getType = classmethod(getType)
+
+ def __init__(self, vm, recreate=False):
self.destroyed = False
self.vm = vm
self.deviceId = 0
self.devices = {}
self.device_order = []
- def getType(self):
- return self.dctype.getType()
-
def getDevControllerType(self):
return self.dctype
# Redefinitions must have the same arguments.
def initController(self, recreate=False, reboot=False):
+ """Initialise the controller. Called when the controller is
+ first created, and again after the domain is rebooted (with reboot True).
+ If called with recreate True (and reboot False) the controller is being
+ recreated after a xend restart.
+
+ As this can be a re-init (after reboot) any controller state should
+ be reset. For example the destroyed flag.
+ """
self.destroyed = False
if reboot:
self.rebootDevices()
def newDevice(self, id, config, recreate=False):
"""Create a device with the given config.
Must be defined in subclass.
+ Called with recreate True when the device is being recreated after a
+ xend restart.
@return device
"""
raise NotImplementedError()
def createDevice(self, config, recreate=False, change=False):
+ """Create a device and attach to its front- and back-ends.
+ If recreate is true the device is being recreated after a xend restart.
+ If change is true the device is a change to an existing domain,
+ i.e. it is being added at runtime rather than when the domain is created.
+ """
dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
dev.init(recreate=recreate)
self.addDevice(dev)
def destroyDevice(self, id, change=False, reboot=False):
"""Destroy a device.
- May be defined in subclass."""
+ May be defined in subclass.
+
+ If reboot is true the device is being destroyed for a domain reboot.
+
+ The device is not deleted, since it may be recreated later.
+ """
dev = self.getDevice(id)
if not dev:
raise XendError("invalid device id: " + id)
return dev
def deleteDevice(self, id, change=True):
+ """Destroy a device and delete it.
+ Normally called to remove a device from a domain at runtime.
+ """
dev = self.destroyDevice(id, change=change)
self.removeDevice(dev)
def destroyController(self, reboot=False):
"""Destroy all devices and clean up.
- May be defined in subclass."""
+ May be defined in subclass.
+ If reboot is true the controller is being destroyed for a domain reboot.
+ Called at domain shutdown.
+ """
self.destroyed = True
self.destroyDevices(reboot=reboot)
"""Initialization. Called on initial create (when reboot is False)
and on reboot (when reboot is True). When xend is restarting is
called with recreate True. Define in subclass if needed.
+
+ Device instance variables must be defined in the class constructor,
+ but given null or default values. The real values should be initialised
+ in this method. This allows devices to be re-initialised.
+
+ Since this can be called to re-initialise a device any state flags
+ should be reset.
"""
self.destroyed = False
pass
def reboot(self):
- """Reconnect device when the domain is rebooted.
+ """Reconnect the device when the domain is rebooted.
"""
self.init(reboot=True)
self.attach()
If change is True notify destruction (runtime change).
If reboot is True the device is being destroyed for a reboot.
Redefine in subclass if needed.
+
+ Called at domain shutdown and when a device is deleted from
+ a running domain (with change True).
"""
self.destroyed = True
pass
"""Network interface controller. Handles all network devices for a domain.
"""
- def __init__(self, dctype, vm, recreate=False):
- DevController.__init__(self, dctype, vm, recreate=recreate)
+ def __init__(self, vm, recreate=False):
+ DevController.__init__(self, vm, recreate=recreate)
self.channel = None
self.rcvr = None
self.channel = None
for a domain.
"""
- def __init__(self, dctype, vm, recreate=False):
+ def __init__(self, vm, recreate=False):
"""Create a USB device controller.
"""
- DevController.__init__(self, dctype, vm, recreate=recreate)
+ DevController.__init__(self, vm, recreate=recreate)
self.backends = {}
self.backendId = 0
self.rcvr = None